import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
  updateBuckets,
  startUpdateBuckets,
  selectBucket
} from '../actions/s3bucket';
import { selectAccount } from '../actions/s3account';
import {
  fetchKeys,
  updateKeys,
  checkKey,
  uncheckKey,
  updateKeyMetada
} from '../actions/s3key';
import { readCurrentS3Creadential } from '../functions/ConfigManager';
import { getS3Manager } from '../functions/S3Manager';
import { selectNewAccount } from '../utils/AccountReactor';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Checkbox from '@material-ui/core/Checkbox';
import CircularProgress from '@material-ui/core/CircularProgress';
import IconButton from '@material-ui/core/IconButton';
import BackIcon from '@material-ui/icons/KeyboardBackspace';
import CopyIcon from '@material-ui/icons/FileCopy';
import RefreshIcon from '@material-ui/icons/Refresh';
import Chip from '@material-ui/core/Chip';
import './S3MainPage.css';

const { clipboard } = require('electron');

class S3MainPage extends Component {
  componentDidMount = () => {
    readCurrentS3Creadential(currentAccount => {
      if (currentAccount) {
        this.props.initBuckets(currentAccount);
      } else {
        console.log('No S3 Account is selected');
      }
    });
  };

  selectBucket = bucket => {
    return () => {
      this.props.selectS3Bucket(bucket, this.props.currentS3Account);
    };
  };

  handleKeyClick = key => {
    return event => {
      const { prefix, currentS3Bucket } = this.props;
      const s3Manager = getS3Manager();

      if (key.indexOf('/') < 0) {
        //Only handle the click for folder
        s3Manager.describeS3Object(currentS3Bucket, prefix + key, data => {
          this.props.updateKeyMetada({
            ...data,
            key: prefix + key
          });
          console.log('ContentLength: ' + data.ContentLength);
         
        });
        return;
      }

      this.props.updateKeyMetada({});

      const newPrefix = prefix + key;

      this.props.fetchKeys();
      s3Manager.listNextLayerKeys(currentS3Bucket, newPrefix, keys => {
        this.props.updateKeys(keys, newPrefix);
      });
    };
  };

  toLastLayer = () => {
    const { prefix, currentS3Bucket } = this.props;
    let newPrefix = prefix.slice(0, prefix.length - 1);
    const index = newPrefix.lastIndexOf('/') + 1;
    newPrefix = newPrefix.slice(0, index);
    const s3Manager = getS3Manager();
    this.props.fetchKeys();
    s3Manager.listNextLayerKeys(currentS3Bucket, newPrefix, keys => {
      this.props.updateKeys(keys, newPrefix);
    });
  };

  refreshKeys = () => {
    const { prefix, currentS3Bucket } = this.props;
    const s3Manager = getS3Manager();
    this.props.fetchKeys();
    s3Manager.listNextLayerKeys(currentS3Bucket, prefix, keys => {
      this.props.updateKeys(keys, prefix);
    });
  };

  toggleKeyCheck = key => {
    return event => {
      this.props.toggleKeyCheckStatus([key], event.target.checked);
    };
  };

  toggleKeyAllSelect = event =>{
    if(event.target.checked){
      let unCheckedKeys = this.props.s3keys.filter(key => key.indexOf('/') === -1);
      this.props.checkedS3keys.forEach(k=>unCheckedKeys.splice(unCheckedKeys.indexOf(k),1) )
      this.props.toggleKeyCheckStatus(unCheckedKeys, event.target.checked);
    }else{
      this.props.toggleKeyCheckStatus(this.props.checkedS3keys, event.target.checked);
    }
  }

  // todo 
  copyKey = () => {
    const { checkedS3keys, prefix } = this.props;
    if (checkedS3keys.length > 0) {
      clipboard.writeText(prefix + checkedS3keys[0], 's3key');
      alert("current s3 object's key is copied into your clipboard");
    } else {
      clipboard.writeText(prefix, 's3key');
      alert('current s3 path is copied into your clipboard');
    }
  };

  render() {
    const {
      currentS3Account,
      buckets,
      currentS3Bucket,
      s3keys,
      checkedS3keys,
      isFetchingKeys,
      isUpdatingBuckets,
      prefix,
      currentObjectMeta
    } = this.props;

    return (
      <div id="main-panel">
        <div id="buckets-nav">
          <p id="account-name-label">
            {currentS3Account.name}
          </p>
          {isUpdatingBuckets ? (
            <CircularProgress style={{ marginTop: 50 }} />
          ) : (
            <List
              component="nav"
              style={{
                height: '85vh',
                overflow: 'auto'
              }}
            >        
              {buckets.map(bucket => (
                <ListItem
                  button
                  selected={bucket === currentS3Bucket}
                  key={bucket}                 
                  onClick={this.selectBucket(bucket)}
                >
                  <ListItemText primary={bucket}  className="bucketItem"/>
                </ListItem>
              ))}
            </List>
          )}
        </div>

        <div id="objects-container">
          <p id="object-operation-bar">
            <IconButton
              aria-label="back"
              color="primary"
              disabled={!prefix}
              onClick={this.toLastLayer}
            >
              <BackIcon />
            </IconButton>
            <IconButton
              aria-label="refresh"
              color="primary"
              onClick={this.refreshKeys}
            >
              <RefreshIcon />
            </IconButton>
           
            <span> {prefix} </span>
          </p>

          {isFetchingKeys ? (
            <CircularProgress style={{ marginTop: 50 }} />
          ) : (
            <List
              component="nav"
              dense
              style={{
                overflow: 'auto',
                maxHeight: '85vh'
              }}
            >
               { s3keys && s3keys.length > 0 &&  <ListItem
                  button       
                  key="all-select"                                   
                >
                <Checkbox                                          
                      disableRipple    
                      onChange={this.toggleKeyAllSelect}                  
                    />
                  <ListItemText primary={"Select All"}  className="bucketItem"/>
                </ListItem>
              }

              {s3keys.map(key => {
                const isChecked = checkedS3keys.indexOf(key) > -1;
                const isFolder = key.indexOf('/') > -1;

                return (
                  <ListItem button key={key} onClick={this.handleKeyClick(key)}>
                    <Checkbox
                      disabled={isFolder}
                      checked={isChecked}                      
                      disableRipple
                      onChange={this.toggleKeyCheck(key)}
                    />
                    <ListItemText primary={key} />
                  </ListItem>
                );
              })}
            </List>
          )}
        </div>

        {
          currentObjectMeta && currentObjectMeta.key ? (
            <div id="s3-object-meta-info-container">
              <p id="meta-info-header">Metadata Information</p>
              <p>
                <Chip label="Key" color="secondary"/> 
                <span className="meta-value">{currentObjectMeta.key}</span>
              </p>
              {currentObjectMeta.Expires && (
                <p><Chip label="Expires Date" color="secondary"/> 
                <span className="meta-value">{currentObjectMeta.Expires.toISOString()}</span>
                </p>
              )}
              {currentObjectMeta.LastModified && (
                <p>
                  <Chip label="LastModified" color="secondary"/> 
                  <span className="meta-value">{currentObjectMeta.LastModified.toISOString()}</span>
                </p>
              )}
              <p>
                <Chip label="ContentLength" color="secondary"/> 
                <span className="meta-value">{currentObjectMeta.ContentLength}</span>
              </p>
              <p>
                <Chip label="ContentType" color="secondary"/> 
                <span className="meta-value">{currentObjectMeta.ContentType}</span>
              </p>
            </div>
            ) 
            : null
        }
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    currentS3Account: state.s3account.currentAccount,
    buckets: state.s3bucket.buckets,
    currentS3Bucket: state.s3bucket.currentBucket,
    isUpdatingBuckets: state.s3bucket.isUpdatingBuckets,
    isFetchingKeys: state.s3key.isFetchingKeys,
    s3keys: state.s3key.s3keys,
    checkedS3keys: state.s3key.checkedS3keys,
    prefix: state.s3key.prefix,
    currentObjectMeta: state.s3key.metadata
  };
}

function mapDispatchToProps(dispatch) {
  const convertor = {
    initBuckets: account => {
      const s3Manager = getS3Manager(account);
      selectNewAccount(dispatch, account, s3Manager);
    },
    updateS3Buckets: buckets => {
      dispatch(updateBuckets(buckets));
    },
    selectS3Bucket: (bucket, currentS3Account) => {
      dispatch(selectBucket(bucket));
      const s3Manager = getS3Manager(currentS3Account);

      convertor.fetchKeys();
      s3Manager.listOneLayerKeys(bucket, keys => {
        convertor.updateKeys(keys, '');
      });
    },
    fetchKeys: () => {
      dispatch(fetchKeys());
    },
    updateKeys: (s3keys, prefix) => {
      dispatch(updateKeys(s3keys, prefix));
    },
    toggleKeyCheckStatus: (keys, checked) => {
      if (checked) {
        dispatch(checkKey(keys));
      } else {
        dispatch(uncheckKey(keys));
      }
    },
    updateKeyMetada: meta => {
      dispatch(updateKeyMetada(meta));
    }
  };

  return convertor;
}

export default connect(
  mapStateToProps,
  mapDispatchToProps,
  null,
  { withRef: true }
)(S3MainPage);
